/*
 * code4adresses.c
 *
 *  Created on: 22 déc. 2011
 *      Author: arthur
 */

#include "code4adresses.h"

int arg1estEcrit(enum instructionMIPS instr) {
	int res = 0;//par défault, le premier argument sert à stocker le résultat

	//liste des instruction n'écrivant pasdans le premier argument.
	if (instr == b || instr == beq || instr == bgez || instr == bgezal || instr
			== bgtz || instr == blez || instr == bltz || instr == bltzal
			|| instr == bgt || instr == blt || instr == bne || instr == bnez
			|| instr == beqz || instr == j || instr == jal || instr == label) {
		res = 1;
	}

	return res;
}

//Retourne le nombre d'argument necessaire à l'instruction
int nbArg(enum instructionMIPS instr) {
	int res = 0;

	//Instructions avec 3 argument
	if (instr == add || instr == addi || instr == addu || instr == addiu
			|| instr == divMIPS || instr == mul || instr == mulo || instr
			== mulou || instr == rem || instr == remu || instr == sub || instr
			== subu || instr == and || instr == andi || instr == or || instr
			== ori || instr == xor || instr == xori || instr == rol || instr
			== ror || instr == sll || instr == sllv || instr == sra || instr
			== srav || instr == srl || instr == srlv || instr == seq || instr
			== sge || instr == sgeu || instr == sgt || instr == sgtu || instr
			== sle || instr == sleu || instr == slt || instr == slti || instr
			== sltu || instr == sltiu || instr == sne) {
		res = 3;
	} else if (instr == not || instr == beq || instr == bgt || instr == blt
			|| instr == bne || instr == la || instr == lw || instr == li
			|| instr == sw || instr == move) {
		res = 2;
	} else if (instr == bgez || instr == bgezal || instr == bgtz || instr
			== blez || instr == bltz || instr == bltzal || instr == beqz
			|| instr == bnez || instr == liChaine) {
		res = 1;
	}

	return res;
}
int estUnSaut(enum instructionMIPS instr) {
	int res = 0;//par défault, le premier argument sert à stocker le résultat

	//liste des instruction n'écrivant dans le premier argument.
	if (instr == b || instr == beq || instr == bgez || instr == bgezal || instr
			== bgtz || instr == blez || instr == bltz || instr == bltzal
			|| instr == bgt || instr == blt || instr == bnez || instr == bne
			|| instr == beqz || instr == j || instr == jal || instr == liChaine) {
		res = 1;
	}

	return res;
}

char * nomInstr(enum instructionMIPS instr) {
	char * res;
	switch (instr) {
	case syscall:
		res = "syscall";
		break;
	case liChaine:
		res = "la";
		break;
	case add:
		res = "add";
		break;
	case addi:
		res = "addi";
		break;
	case addu:
		res = "addu";
		break;
	case addiu:
		res = "addiu";
		break;
	case divMIPS:
		res = "div";
		break;
	case mul:
		res = "mul";
		break;
	case mulo:
		res = "mulo";
		break;
	case mulou:
		res = "mulou";
		break;
	case rem:
		res = "rem";
		break;
	case remu:
		res = "remu";
		break;
	case sub:
		res = "sub";
		break;
	case subu:
		res = "subu";
		break;
	case and:
		res = "and";
		break;
	case andi:
		res = "andi";
		break;
	case not:
		res = "not";
		break;
	case or:
		res = "or";
		break;
	case ori:
		res = "ori";
		break;
	case xor:
		res = "xor";
		break;
	case xori:
		res = "xori";
		break;
	case rol:
		res = "rol";
		break;
	case ror:
		res = "ror";
		break;
	case sll:
		res = "sll";
		break;
	case sllv:
		res = "sllv";
		break;
	case sra:
		res = "sra";
		break;
	case srav:
		res = "srav";
		break;
	case srl:
		res = "srl";
		break;
	case srlv:
		res = "srlv";
		break;
	case seq:
		res = "seq";
		break;
	case sge:
		res = "sge";
		break;
	case sgeu:
		res = "sgeu";
		break;
	case sgt:
		res = "sgt";
		break;
	case sgtu:
		res = "sgtu";
		break;
	case sle:
		res = "sle";
		break;
	case sleu:
		res = "sleu";
		break;
	case slt:
		res = "slt";
		break;
	case slti:
		res = "slti";
		break;
	case sltu:
		res = "sltu";
		break;
	case sltiu:
		res = "sltiu";
		break;
	case sne:
		res = "sne";
		break;
	case b:
		res = "b";
		break;
	case beq:
		res = "beq";
		break;
	case beqz:
		res = "beqz";
		break;
	case bgez:
		res = "bgez";
		break;
	case bgezal:
		res = "bgezal";
		break;
	case bgtz:
		res = "bgtz";
		break;
	case blez:
		res = "blez";
		break;
	case bltz:
		res = "bltz";
		break;
	case bltzal:
		res = "bltzal";
		break;
	case bgt:
		res = "bgt";
		break;
	case blt:
		res = "blt";
		break;
	case bne:
		res = "bne";
		break;
	case bnez:
		res = "bnez";
		break;
	case j:
		res = "j";
		break;
	case jal:
		res = "jal";
		break;
	case la:
		res = "la";
		break;
	case lw:
		res = "lw";
		break;
	case li:
		res = "li";
		break;
	case sw:
		res = "sw";
		break;
	case move:
		res = "move";
		break;
	case nop:
		res = "nop";
		break;
	case label:
		res = "";
		break;
	default:
		res = "";
	}

	return res;
}

char * nomReg(enum registres reg) {
	char * res;
	switch (reg) {
	case r0:
		res = "$r0";
		break;
	case at:
		res = "$at";
		break;
	case v0:
		res = "$v0";
		break;
	case v1:
		res = "$v1";
		break;
	case a0:
		res = "$a0";
		break;
	case a1:
		res = "$a1";
		break;
	case a2:
		res = "$a2";
		break;
	case a3:
		res = "$a3";
		break;
	case t0:
		res = "$t0";
		break;
	case t1:
		res = "$t1";
		break;
	case t2:
		res = "$t2";
		break;
	case t3:
		res = "$t3";
		break;
	case t4:
		res = "$t4";
		break;
	case t5:
		res = "$t5";
		break;
	case t6:
		res = "$t6";
		break;
	case t7:
		res = "$t7";
		break;
	case s0:
		res = "$s0";
		break;
	case s1:
		res = "$s1";
		break;
	case s2:
		res = "$s2";
		break;
	case s3:
		res = "$s3";
		break;
	case s4:
		res = "$s4";
		break;
	case s5:
		res = "$s5";
		break;
	case s6:
		res = "$s6";
		break;
	case s7:
		res = "$s7";
		break;
	case t8:
		res = "$t8";
		break;
	case t9:
		res = "$t9";
		break;
	case k0:
		res = "$k0";
		break;
	case k1:
		res = "$k1";
		break;
	case gp1:
		res = "$gp1";
		break;
	case s8:
		res = "$s8";
		break;
	case ra:
		res = "$ra";
		break;
	default:
		res = "$r0";
		break;
	}

	return res;
}

code4adresses * genCode(char * label, enum instructionMIPS op, int arg1,
		int arg2, int arg3, int typeArg1, int typeArg2, int typeArg3) {

	code4adresses * instruction = (code4adresses *) calloc(1,
			sizeof(code4adresses));

	instruction->label = label;
	instruction->instruction = op;
	instruction->arg1 = arg1;
	instruction->arg2 = arg2;
	instruction->arg3 = arg3;

	unsigned char typeArgs = (typeArg1 % 2);
	typeArgs += (typeArg2 % 2) * 2;
	typeArgs += (typeArg3 % 2) * 4;

	instruction->typeArgs = typeArgs;

	if (premiereOperation == NULL) {
		premiereOperation = instruction;
		operationCourante = instruction;
	} else if (operationCourante != NULL) {
		((code4adresses *) operationCourante)->suivant = instruction;
		instruction->precedent = operationCourante;
		operationCourante = instruction;
	}

	return instruction;
}

//int pile_operande[64];
//int pile_type_operande[64];
//int cur_index_operande = 0;
//int pile_operation[64];
//int cur_index_operation = 0;
//#define AFF 1
//#define ADD 2

int genAff() {

	char * label1Op = labelPremiereOp;
	labelPremiereOp = NULL;


	int opCourante;
	int operande1;
	int typeOperande1;
	int operande2;
	int typeOperande2;
	int operande3;
	int typeOperande3;

	while (cur_index_operation >= 0 && pile_operation[cur_index_operation]
			!= AFF) {
		opCourante = pile_operation[--cur_index_operation];//depiler
		operande1 = 0;
		typeOperande1 = 1;
		operande2 = 0;
		typeOperande2 = 1;
		operande3 = 0;
		typeOperande3 = 1;

		if (pile_operation[cur_index_operation - 1] == PARENTHESE_FERMANTE) {
			cur_index_operation--; //effacement de la parenthese fermante
			//Sauvegarde de l'opération courante et du dernier argument et de l'operation courante,
			//calcul du contenu de la parenthèse, puis réempilement de l'argument
			int opSauvegarde = opCourante;
			int argSauvegarde = pile_operande[--cur_index_operande];
			int typeArgSauvegarde = pile_type_operande[cur_index_operande];

			genOpArithmetiqueOuBooleeneParentheses();

			opCourante = opSauvegarde;
			pile_operande[cur_index_operande] = argSauvegarde;
			pile_type_operande[cur_index_operande++] = typeArgSauvegarde;

			genOpArithmetiqueOuBooleene(opCourante);

		} else {
			genOpArithmetiqueOuBooleene(opCourante);
		}
	}
	if (cur_index_operation >= 0 && pile_operation[cur_index_operation] == AFF) {

		opCourante = pile_operation[--cur_index_operation];//depiler
		if (cur_index_operande == 2) {
			operande2 = pile_operande[--cur_index_operande];
			typeOperande2 = pile_type_operande[cur_index_operande];
			operande1 = pile_operande[--cur_index_operande];
			typeOperande1 = pile_type_operande[cur_index_operande];
			enum instructionMIPS instructionMips = move;
			if (typeOperande2 == 0) {
				instructionMips = li;
			}
			genCode(label1Op, instructionMips, operande1, operande2, operande3,
					typeOperande1, typeOperande2, typeOperande3);
			label1Op = NULL;
		} else {
			return 2;
		}
	}
	return 0;
}

int genOpArithmetiqueOuBooleene(int opCourante) {
	char * label1Op = labelPremiereOp;
	labelPremiereOp = NULL;

	int operande1 = 0;
	int typeOperande1 = 1;
	int operande2 = 0;
	int typeOperande2 = 1;
	int operande3 = 0;
	int typeOperande3 = 1;

	switch (opCourante) {
	case ADD:
		if (cur_index_operande > 2) {
			operande3 = pile_operande[--cur_index_operande];
			typeOperande3 = pile_type_operande[cur_index_operande];
			operande2 = pile_operande[--cur_index_operande];
			typeOperande2 = pile_type_operande[cur_index_operande];

			if (typeOperande3 == 0 && typeOperande2 == 1) {
				operande1 = compteur_numVarTmp--;
				typeOperande1 = 1;
				genCode(label1Op, addi, operande1, operande2, operande3,
						typeOperande1, typeOperande2, typeOperande3);
				label1Op = NULL;
			} else if (typeOperande3 == 1 && typeOperande2 == 0) {
				operande1 = compteur_numVarTmp--;
				typeOperande1 = 1;
				genCode(label1Op, addi, operande1, operande3, operande2,
						typeOperande1, typeOperande3, typeOperande2);
				label1Op = NULL;
			} else if (typeOperande3 == 1 && typeOperande2 == 1) {
				operande1 = compteur_numVarTmp--;
				typeOperande1 = 1;
				genCode(label1Op, add, operande1, operande2, operande3,
						typeOperande1, typeOperande2, typeOperande3);
				label1Op = NULL;
			} else {
				//les deux operandes sont des constantes, on les addictionnes donc et on empile le résultat
				operande1 = operande2 + operande3;
				typeOperande1 = 0;
			}

			derniereExpr = operande1;
			typrDerniereExpr = typeOperande1;
			pile_operande[cur_index_operande] = operande1;
			pile_type_operande[cur_index_operande++] = typeOperande1;
		} else {
			return 1;
		}
		break;
	case SUB:
		if (cur_index_operande > 2) {
			operande3 = pile_operande[--cur_index_operande];
			typeOperande3 = pile_type_operande[cur_index_operande];
			operande2 = pile_operande[--cur_index_operande];
			typeOperande2 = pile_type_operande[cur_index_operande];

			if (typeOperande3 == 0 && typeOperande2 == 0) {
				operande1 = operande2 - operande3;
				typeOperande1 = 0;
			} else {
				if (typeOperande3 == 0) {
					genCode(label1Op, li, a0, operande3, 0, 1, typeOperande3, 1);
					label1Op = NULL;
					operande3 = a0;
					typeOperande3 = 1;
				}
				if (typeOperande2 == 0) {
					genCode(label1Op, li, a1, operande2, 0, 1, typeOperande2, 1);
					label1Op = NULL;
					operande2 = a1;
					typeOperande2 = 1;
				}

				operande1 = compteur_numVarTmp--;
				typeOperande1 = 1;

				genCode(label1Op, sub, operande1, operande2, operande3,
						typeOperande1, typeOperande2, typeOperande3);
				label1Op = NULL;
			}

			pile_operande[cur_index_operande] = operande1;
			pile_type_operande[cur_index_operande++] = typeOperande1;
		} else {
			return 1;
		}
		break;
	case MUL:
		if (cur_index_operande > 2) {
			operande3 = pile_operande[--cur_index_operande];
			typeOperande3 = pile_type_operande[cur_index_operande];
			operande2 = pile_operande[--cur_index_operande];
			typeOperande2 = pile_type_operande[cur_index_operande];

			if (typeOperande3 == 0 && typeOperande2 == 0) {
				operande1 = operande2 * operande3;
				typeOperande1 = 0;
			} else {
				if (typeOperande3 == 0) {
					genCode(label1Op, li, a0, operande3, 0, 1, typeOperande3, 1);
					label1Op = NULL;
					operande3 = a0;
					typeOperande3 = 1;
				}
				if (typeOperande2 == 0) {
					genCode(label1Op, li, a1, operande2, 0, 1, typeOperande2, 1);
					label1Op = NULL;
					operande2 = a1;
					typeOperande2 = 1;
				}

				operande1 = compteur_numVarTmp--;
				typeOperande1 = 1;

				genCode(label1Op, mul, operande1, operande2, operande3,
						typeOperande1, typeOperande2, typeOperande3);
				label1Op = NULL;
			}

			pile_operande[cur_index_operande] = operande1;
			pile_type_operande[cur_index_operande++] = typeOperande1;
		} else {
			return 1;
		}
		break;
	case DIV:
		if (cur_index_operande > 2) {
			operande3 = pile_operande[--cur_index_operande];
			typeOperande3 = pile_type_operande[cur_index_operande];
			operande2 = pile_operande[--cur_index_operande];
			typeOperande2 = pile_type_operande[cur_index_operande];

			if (typeOperande3 == 0 && typeOperande2 == 0) {
				operande1 = operande2 / operande3;
				typeOperande1 = 0;
			} else {
				if (typeOperande3 == 0) {
					genCode(label1Op, li, a0, operande3, 0, 1, typeOperande3, 1);
					label1Op = NULL;
					operande3 = a0;
					typeOperande3 = 1;
				}
				if (typeOperande2 == 0) {
					genCode(label1Op, li, a1, operande2, 0, 1, typeOperande2, 1);
					label1Op = NULL;
					operande2 = a1;
					typeOperande2 = 1;
				}

				operande1 = compteur_numVarTmp--;
				typeOperande1 = 1;

				genCode(label1Op, divMIPS, operande1, operande2, operande3,
						typeOperande1, typeOperande2, typeOperande3);
				label1Op = NULL;
			}

			pile_operande[cur_index_operande] = operande1;
			pile_type_operande[cur_index_operande++] = typeOperande1;
		} else {
			return 1;
		}
		break;

	case POW:
		if (cur_index_operande > 2) {
			operande3 = pile_operande[--cur_index_operande];
			typeOperande3 = pile_type_operande[cur_index_operande];
			operande2 = pile_operande[--cur_index_operande];
			typeOperande2 = pile_type_operande[cur_index_operande];

			if (typeOperande3 == 0 && typeOperande2 == 0) {
				operande1 = (int) powf((float) operande2, (float) operande3);
				typeOperande1 = 0;
			} else {
				if (typeOperande3 == 0) {
					genCode(label1Op, li, t0, operande3, 0, 1, typeOperande3, 1);
					label1Op = NULL;
					operande3 = t0;
					typeOperande3 = 1;
				} else {
					genCode(label1Op, move, t0, operande3, 0, 1, typeOperande3,
							1);
					label1Op = NULL;
					operande3 = t0;
					typeOperande3 = 1;
				}
				if (typeOperande2 == 0) {
					genCode(label1Op, li, a0, operande2, 0, 1, typeOperande2, 1);
					label1Op = NULL;
					operande2 = a0;
					typeOperande2 = 1;
				} else {
					genCode(label1Op, move, a0, operande2, 0, 1, typeOperande2,
							1);
					label1Op = NULL;
					operande2 = a0;
					typeOperande2 = 1;
				}

				genCode(label1Op, li, v0, 1, 0, 1, 0, 1);
				label1Op = NULL;

				//generation des labels
				char * labelPowDebut = (char *) calloc(16, sizeof(char));
				char * labelPowFin = (char *) calloc(16, sizeof(char));
				snprintf(labelPowDebut, 16, "pow%xd", compteurPOW);
				snprintf(labelPowFin, 16, "pow%xf", compteurPOW++);

				genCode(labelPowFin, blez, t0, r0, r0, 1, 1, 1);
				genCode(labelPowDebut, mul, v0, v0, a0, 1, 1, 1);
				genCode(NULL, addi, t0, t0, -1, 1, 1, 0);
				genCode(labelPowDebut, bgtz, t0, r0, r0, 1, 1, 1);

				operande1 = compteur_numVarTmp--;
				typeOperande1 = 1;

				genCode(labelPowFin, move, operande1, v0, r0, typeOperande1, 1,
						1);

			}

			pile_operande[cur_index_operande] = operande1;
			pile_type_operande[cur_index_operande++] = typeOperande1;
		} else {
			return 1;
		}
		break;
	case LT:
		if (cur_index_operande > 2) {
			operande3 = pile_operande[--cur_index_operande];
			typeOperande3 = pile_type_operande[cur_index_operande];
			operande2 = pile_operande[--cur_index_operande];
			typeOperande2 = pile_type_operande[cur_index_operande];

			if (typeOperande3 == 0 && typeOperande2 == 0) {
				operande1 = (operande2 < operande3);
				typeOperande1 = 0;
			} else {
				if (typeOperande3 == 0) {
					genCode(label1Op, li, a0, operande3, 0, 1, typeOperande3, 1);
					label1Op = NULL;
					operande3 = a0;
					typeOperande3 = 1;
				}
				if (typeOperande2 == 0) {
					genCode(label1Op, li, a1, operande2, 0, 1, typeOperande2, 1);
					label1Op = NULL;
					operande2 = a1;
					typeOperande2 = 1;
				}

				operande1 = compteur_numVarTmp--;
				typeOperande1 = 1;

				genCode(label1Op, slt, operande1, operande2, operande3,
						typeOperande1, typeOperande2, typeOperande3);
				label1Op = NULL;
			}

			pile_operande[cur_index_operande] = operande1;
			pile_type_operande[cur_index_operande++] = typeOperande1;
		} else {
			return 1;
		}
		break;
	case LET:
		if (cur_index_operande > 2) {
			operande3 = pile_operande[--cur_index_operande];
			typeOperande3 = pile_type_operande[cur_index_operande];
			operande2 = pile_operande[--cur_index_operande];
			typeOperande2 = pile_type_operande[cur_index_operande];

			if (typeOperande3 == 0 && typeOperande2 == 0) {
				operande1 = (operande2 <= operande3);
				typeOperande1 = 0;
			} else {
				if (typeOperande3 == 0) {
					genCode(label1Op, li, a0, operande3, 0, 1, typeOperande3, 1);
					label1Op = NULL;
					operande3 = a0;
					typeOperande3 = 1;
				}
				if (typeOperande2 == 0) {
					genCode(label1Op, li, a1, operande2, 0, 1, typeOperande2, 1);
					label1Op = NULL;
					operande2 = a1;
					typeOperande2 = 1;
				}

				operande1 = compteur_numVarTmp--;
				typeOperande1 = 1;

				genCode(label1Op, sle, operande1, operande2, operande3,
						typeOperande1, typeOperande2, typeOperande3);
				label1Op = NULL;
			}

			pile_operande[cur_index_operande] = operande1;
			pile_type_operande[cur_index_operande++] = typeOperande1;
		} else {
			return 1;
		}
		break;
	case GET:
		if (cur_index_operande > 2) {
			operande3 = pile_operande[--cur_index_operande];
			typeOperande3 = pile_type_operande[cur_index_operande];
			operande2 = pile_operande[--cur_index_operande];
			typeOperande2 = pile_type_operande[cur_index_operande];

			if (typeOperande3 == 0 && typeOperande2 == 0) {
				operande1 = (operande2 >= operande3);
				typeOperande1 = 0;
			} else {
				if (typeOperande3 == 0) {
					genCode(label1Op, li, a0, operande3, 0, 1, typeOperande3, 1);
					label1Op = NULL;
					operande3 = a0;
					typeOperande3 = 1;
				}
				if (typeOperande2 == 0) {
					genCode(label1Op, li, a1, operande2, 0, 1, typeOperande2, 1);
					label1Op = NULL;
					operande2 = a1;
					typeOperande2 = 1;
				}

				operande1 = compteur_numVarTmp--;
				typeOperande1 = 1;

				genCode(label1Op, sge, operande1, operande2, operande3,
						typeOperande1, typeOperande2, typeOperande3);
				label1Op = NULL;
			}

			pile_operande[cur_index_operande] = operande1;
			pile_type_operande[cur_index_operande++] = typeOperande1;
		} else {
			return 1;
		}
		break;
	case GT:
		if (cur_index_operande > 2) {
			operande3 = pile_operande[--cur_index_operande];
			typeOperande3 = pile_type_operande[cur_index_operande];
			operande2 = pile_operande[--cur_index_operande];
			typeOperande2 = pile_type_operande[cur_index_operande];

			if (typeOperande3 == 0 && typeOperande2 == 0) {
				operande1 = (operande2 > operande3);
				typeOperande1 = 0;
			} else {
				if (typeOperande3 == 0) {
					genCode(label1Op, li, a0, operande3, 0, 1, typeOperande3, 1);
					label1Op = NULL;
					operande3 = a0;
					typeOperande3 = 1;
				}
				if (typeOperande2 == 0) {
					genCode(label1Op, li, a1, operande2, 0, 1, typeOperande2, 1);
					label1Op = NULL;
					operande2 = a1;
					typeOperande2 = 1;
				}

				operande1 = compteur_numVarTmp--;
				typeOperande1 = 1;

				genCode(label1Op, sgt, operande1, operande2, operande3,
						typeOperande1, typeOperande2, typeOperande3);
				label1Op = NULL;
			}

			pile_operande[cur_index_operande] = operande1;
			pile_type_operande[cur_index_operande++] = typeOperande1;
		} else {
			return 1;
		}
		break;
	case EQ:
		if (cur_index_operande > 2) {
			operande3 = pile_operande[--cur_index_operande];
			typeOperande3 = pile_type_operande[cur_index_operande];
			operande2 = pile_operande[--cur_index_operande];
			typeOperande2 = pile_type_operande[cur_index_operande];

			if (typeOperande3 == 0 && typeOperande2 == 0) {
				operande1 = (operande2 == operande3);
				typeOperande1 = 0;
			} else {
				if (typeOperande3 == 0) {
					genCode(label1Op, li, a0, operande3, 0, 1, typeOperande3, 1);
					label1Op = NULL;
					operande3 = a0;
					typeOperande3 = 1;
				}
				if (typeOperande2 == 0) {
					genCode(label1Op, li, a1, operande2, 0, 1, typeOperande2, 1);
					label1Op = NULL;
					operande2 = a1;
					typeOperande2 = 1;
				}

				operande1 = compteur_numVarTmp--;
				typeOperande1 = 1;

				genCode(label1Op, seq, operande1, operande2, operande3,
						typeOperande1, typeOperande2, typeOperande3);
				label1Op = NULL;
			}

			pile_operande[cur_index_operande] = operande1;
			pile_type_operande[cur_index_operande++] = typeOperande1;
		} else {
			return 1;
		}
		break;
	case DIFF:
		if (cur_index_operande > 2) {
			operande3 = pile_operande[--cur_index_operande];
			typeOperande3 = pile_type_operande[cur_index_operande];
			operande2 = pile_operande[--cur_index_operande];
			typeOperande2 = pile_type_operande[cur_index_operande];

			if (typeOperande3 == 0 && typeOperande2 == 0) {
				operande1 = (operande2 != operande3);
				typeOperande1 = 0;
			} else {
				if (typeOperande3 == 0) {
					genCode(label1Op, li, a0, operande3, 0, 1, typeOperande3, 1);
					label1Op = NULL;
					operande3 = a0;
					typeOperande3 = 1;
				}
				if (typeOperande2 == 0) {
					genCode(label1Op, li, a1, operande2, 0, 1, typeOperande2, 1);
					label1Op = NULL;
					operande2 = a1;
					typeOperande2 = 1;
				}

				operande1 = compteur_numVarTmp--;
				typeOperande1 = 1;

				genCode(label1Op, sne, operande1, operande2, operande3,
						typeOperande1, typeOperande2, typeOperande3);
				label1Op = NULL;
			}

			pile_operande[cur_index_operande] = operande1;
			pile_type_operande[cur_index_operande++] = typeOperande1;
		} else {
			return 1;
		}
		break;
	case AND:
		if (cur_index_operande > 2) {
			operande3 = pile_operande[--cur_index_operande];
			typeOperande3 = pile_type_operande[cur_index_operande];
			operande2 = pile_operande[--cur_index_operande];
			typeOperande2 = pile_type_operande[cur_index_operande];

			if (typeOperande3 == 0 && typeOperande2 == 0) {
				operande1 = (operande2 && operande3);
				typeOperande1 = 0;
			} else {
				if (typeOperande3 == 0) {
					genCode(label1Op, li, a0, operande3, 0, 1, typeOperande3, 1);
					label1Op = NULL;
					operande3 = a0;
					typeOperande3 = 1;
				}
				if (typeOperande2 == 0) {
					genCode(label1Op, li, a1, operande2, 0, 1, typeOperande2, 1);
					label1Op = NULL;
					operande2 = a1;
					typeOperande2 = 1;
				}

				operande1 = compteur_numVarTmp--;
				typeOperande1 = 1;

				genCode(label1Op, and, operande1, operande2, operande3,
						typeOperande1, typeOperande2, typeOperande3);
				label1Op = NULL;
			}

			pile_operande[cur_index_operande] = operande1;
			pile_type_operande[cur_index_operande++] = typeOperande1;
		} else {
			return 1;
		}
		break;
	case OR:
		if (cur_index_operande > 2) {
			operande3 = pile_operande[--cur_index_operande];
			typeOperande3 = pile_type_operande[cur_index_operande];
			operande2 = pile_operande[--cur_index_operande];
			typeOperande2 = pile_type_operande[cur_index_operande];

			if (typeOperande3 == 0 && typeOperande2 == 0) {
				operande1 = (operande2 || operande3);
				typeOperande1 = 0;
			} else {
				if (typeOperande3 == 0) {
					genCode(label1Op, li, a0, operande3, 0, 1, typeOperande3, 1);
					label1Op = NULL;
					operande3 = a0;
					typeOperande3 = 1;
				}
				if (typeOperande2 == 0) {
					genCode(label1Op, li, a1, operande2, 0, 1, typeOperande2, 1);
					label1Op = NULL;
					operande2 = a1;
					typeOperande2 = 1;
				}

				operande1 = compteur_numVarTmp--;
				typeOperande1 = 1;

				genCode(label1Op, or, operande1, operande2, operande3,
						typeOperande1, typeOperande2, typeOperande3);
				label1Op = NULL;
			}

			pile_operande[cur_index_operande] = operande1;
			pile_type_operande[cur_index_operande++] = typeOperande1;
		} else {
			return 1;
		}
		break;
	case XOR:
		if (cur_index_operande > 2) {
			operande3 = pile_operande[--cur_index_operande];
			typeOperande3 = pile_type_operande[cur_index_operande];
			operande2 = pile_operande[--cur_index_operande];
			typeOperande2 = pile_type_operande[cur_index_operande];

			if (typeOperande3 == 0 && typeOperande2 == 0) {
				operande1 = (operande2 ^ operande3);
				typeOperande1 = 0;
			} else {
				if (typeOperande3 == 0) {
					genCode(label1Op, li, a0, operande3, 0, 1, typeOperande3, 1);
					label1Op = NULL;
					operande3 = a0;
					typeOperande3 = 1;
				}
				if (typeOperande2 == 0) {
					genCode(label1Op, li, a1, operande2, 0, 1, typeOperande2, 1);
					label1Op = NULL;
					operande2 = a1;
					typeOperande2 = 1;
				}

				operande1 = compteur_numVarTmp--;
				typeOperande1 = 1;

				genCode(label1Op, xor, operande1, operande2, operande3,
						typeOperande1, typeOperande2, typeOperande3);
				label1Op = NULL;
			}

			pile_operande[cur_index_operande] = operande1;
			pile_type_operande[cur_index_operande++] = typeOperande1;
		} else {
			return 1;
		}
		break;
	case NOT:
		if (cur_index_operande > 2) {
			operande2 = pile_operande[--cur_index_operande];
			typeOperande2 = pile_type_operande[cur_index_operande];

			if (typeOperande3 == 0 && typeOperande2 == 0) {
				operande1 = !operande2;
				typeOperande1 = 0;
			} else {
				if (typeOperande3 == 0) {
					genCode(label1Op, li, a0, operande3, 0, 1, typeOperande3, 1);
					label1Op = NULL;
					operande3 = a0;
					typeOperande3 = 1;
				}
				if (typeOperande2 == 0) {
					genCode(label1Op, li, a1, operande2, 0, 1, typeOperande2, 1);
					label1Op = NULL;
					operande2 = a1;
					typeOperande2 = 1;
				}

				operande1 = compteur_numVarTmp--;
				typeOperande1 = 1;

				genCode(label1Op, not, operande1, operande2, operande3,
						typeOperande1, typeOperande2, typeOperande3);
				label1Op = NULL;
			}

			pile_operande[cur_index_operande] = operande1;
			pile_type_operande[cur_index_operande++] = typeOperande1;
		} else {
			return 1;
		}
		break;
	}
}

int genOpArithmetiqueOuBooleeneParentheses() {
	char * label1Op = labelPremiereOp;
	labelPremiereOp = NULL;

	int opCourante;
	int operande1;
	int typeOperande1;
	int operande2;
	int typeOperande2;
	int operande3;
	int typeOperande3;

	while (cur_index_operation >= 0 && pile_operation[cur_index_operation]
			!= PARENTHESE_OUVRANTE) {
		opCourante = pile_operation[--cur_index_operation];//depiler
		operande1 = 0;
		typeOperande1 = 1;
		operande2 = 0;
		typeOperande2 = 1;
		operande3 = 0;
		typeOperande3 = 1;

		if (pile_operation[cur_index_operation - 1] == PARENTHESE_FERMANTE) {
			cur_index_operation--; //effacement de la parenthese fermante
			//Sauvegarde de l'opération courante et du dernier argument et de l'operation courante,
			//calcul du contenu de la parenthèse, puis réempilement de l'argument
			int opSauvegarde = opCourante;
			int argSauvegarde;
			int typeArgSauvegarde;
			if (opSauvegarde != PARENTHESE_FERMANTE && opSauvegarde
					!= PARENTHESE_OUVRANTE) {
				argSauvegarde = pile_operande[--cur_index_operande];
				typeArgSauvegarde = pile_type_operande[cur_index_operande];
			}

			genOpArithmetiqueOuBooleeneParentheses();

			opCourante = opSauvegarde;
			if (opSauvegarde != PARENTHESE_FERMANTE && opSauvegarde
					!= PARENTHESE_OUVRANTE) {
				pile_operande[cur_index_operande] = argSauvegarde;
				pile_type_operande[cur_index_operande++] = typeArgSauvegarde;
			}

			genOpArithmetiqueOuBooleene(opCourante);

		} else {
			genOpArithmetiqueOuBooleene(opCourante);
		}

	}

	if (cur_index_operation >= 0 && pile_operation[cur_index_operation]
			== PARENTHESE_OUVRANTE) {
		opCourante = pile_operation[--cur_index_operation];//depiler
	} else {
		return 2;
	}

}
